export type UploadHeaders = Record<string, string>;

export interface UploadData {
  [key: string]: any;
}

/**
 *
 */
export type UploadMethod = 'post' | 'put' | 'patch' | 'delete';

/**
 *
 */
export type ListType = 'text' | 'picture' | 'picture-card';

/**
 * 文件信息接口定义
 */
export interface IFileInfo {
  bucketName?: string,
  /**
   * 文件名
   */
  fileName: string,
  /**
   * 文件大小
   */
  fileSize?: number,
  /**
   * 文件路径
   */
  filePath: string,
  /**
   * 文件访问路径
   * @deprecated 请使用 previewUrl
   */
  viewFilePath?: string

  /**
   * 文件预览 URL
   */
  previewUrl?: string
}

/**
 * 原生文件接口定义
 */
export interface IRawFile extends File {
  uid: number,
  uploadId?: string,
  md5?: string
}

/**
 * 上传文件接口定义
 */
export interface IUploadFile<T = { code: number, message: string, data: IFileInfo }> {
  name: string;
  percentage?: number;
  status: 'ready' | 'uploading' | 'success' | 'fail' | 'reading';
  size?: number;
  response?: T;
  uid: number;
  url?: string;
  raw?: IRawFile;
  /**
   * 文件是对象，后端返回的文件对象
   */
  file?: IFileInfo,
}

/**
 * 上传组件属性接口定义
 */
export interface IUploadProps {
  /**
   * 请求 URL
   */
  action?: string;

  /**
   * 设置上传的请求头部
   */
  headers?: UploadHeaders;

  /**
   * 设置上传请求方法，默认使用 'post'
   */
  method?: UploadMethod;

  /**
   * 是否支持多选文件，默认值为 false
   */
  multiple?: boolean;

  /**
   * 上传时附带的额外参数，可以是对象或函数
   * @version 从 v2.3.13 支持 Awaitable 数据和函数
   */
  data?: UploadData | (() => UploadData | Promise<UploadData>);

  /**
   * 上传的文件字段名，默认值为 'file'
   */
  name?: string;

  /**
   * 支持发送 cookie 凭证信息，默认值为 false
   */
  withCredentials?: boolean;

  /**
   * 是否显示已上传文件列表，默认值为 true
   */
  showFileList?: boolean;

  /**
   * 是否启用拖拽上传，默认值为 false
   */
  drag?: boolean;

  /**
   * 接受上传的文件类型， 建议使用 英文逗号分割 例如：'.png,.jpg'
   * @remark thumbnail-mode 模式下此参数无效
   */
  accept?: string;

  /**
   * 原生属性 crossorigin
   */
  crossorigin?: '' | 'anonymous' | 'use-credentials';

  /**
   * 点击文件列表中已上传的文件时的钩子
   */
  onPreview?: (file: IUploadFile) => void;

  /**
   * 文件列表移除文件时的钩子
   */
  onRemove?: (file: IUploadFile, fileList: IUploadFile[]) => void | boolean | Promise<void | boolean>;

  /**
   * 文件上传成功时的钩子
   */
  onSuccess?: (response: {
    code: number,
    data: IFileInfo,
    message: string
  }, file: IUploadFile, fileList: IUploadFile[]) => void;

  /**
   * 文件上传成功处理之前的钩子
   * @param response
   * @param file
   * @param fileList
   */
  beforeSuccess?: (response: {
    code: number,
    data: IFileInfo,
    message: string
  }, file: IUploadFile, fileList: IUploadFile[]) => void | Promise<void>;

  /**
   * 文件上传失败时的钩子
   */
  onError?: (error: any, file: IUploadFile, fileList: IUploadFile[]) => void;

  /**
   * 文件上传时的钩子
   */
  onProgress?: (event: ProgressEvent, file: IUploadFile, fileList: IUploadFile[]) => void;

  /**
   * 文件状态改变时的钩子，添加文件、上传成功和上传失败时都会被调用
   */
  onChange?: (file: IUploadFile, fileList: IUploadFile[]) => void;

  /**
   * 当超出限制时，执行的钩子函数
   */
  onExceed?: (files: File[], fileList: IUploadFile[]) => void;

  /**
   * 文件超时限制时，是否需要替换
   */
  exceedReplace?: boolean

  /**
   * 上传文件之前的钩子，参数为上传的文件
   * @remark 若返回 false 或者返回 Promise 且被 reject，则停止上传
   */
  beforeUpload?: (file: File) => boolean | void | Promise<boolean | void>;

  /**
   * 删除文件之前的钩子，参数为上传的文件和文件列表
   * @remark 若返回 false 或者返回 Promise 且被 reject，则停止删除
   */
  beforeRemove?: (file: IUploadFile, fileList: IUploadFile[]) => boolean | void | Promise<boolean | void>;

  /**
   * 默认上传文件列表
   */
  fileList?: Array<IUploadFile | IFileInfo>;

  /**
   * 文件列表的类型，默认为 'text'
   * text - 文字
   * picture - 图片
   * card - 卡片样式
   * import - 导入样式
   */
  template?: "text" | "picture" | "card" | "import";

  /**
   * 文件列表的类型，默认为 'text'
   */
  listType?: ListType;

  /**
   * 是否自动上传文件，默认值为 true
   */
  autoUpload?: boolean;

  /**
   * 覆盖默认的 Xhr 行为，允许自行实现上传文件的请求
   * @remark 请参考 ajaxUpload 方法
   */
  httpRequest?: (options: any) => void;

  /**
   * 是否禁用上传，默认值为 false
   */
  disabled?: boolean;

  /**
   * 允许上传文件的最大数量
   */
  limit?: number;

  /**
   * 文件尺寸限制，单位 MB
   */
  fileSize?: number;

  /**
   * 提示文字
   */
  placeholder?: string;

  /**
   * 提示文字
   */
  tip?: string;

  /**
   * 是否启用 minio 上传，默认值为 true
   */
  minio?: boolean;

  /**
   * 文件上传路径
   */
  path?: string;
}
